home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DTOSHI2.ZIP / mpgfx / source / gfxgif.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-18  |  20.1 KB  |  886 lines

  1.  
  2. // gfxgif.cpp
  3. //
  4. // Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgfx.h"
  7. #include "gfxgif.h"
  8.  
  9. #define HASH_SIZE 5011
  10. #define HASH_BITS 4
  11. #define CAPACITY  ((long)1<<12)
  12. #define MAXBITS 12
  13.  
  14. struct SEQ_INTERLACED
  15.   {
  16.     INT Start;
  17.     INT Skip;
  18.   }; // End of SEQ_INTERLACED
  19.  
  20. SEQ_INTERLACED InterlacedData[4] =
  21.   {
  22.     { 0, 8 },
  23.     { 4, 8 },
  24.     { 2, 4 },
  25.     { 1, 2 }
  26.   }; // End of InterlacedData
  27.  
  28. GIFFILETOOL::GIFFILETOOL ( FILEHANDLE f ) : IMAGEFILETOOL ( f )
  29.   {
  30.     CodeTable = NULL;
  31.     CodeStack = NULL;
  32.     Prefix = NULL;
  33.     Suffix = NULL;
  34.     DataBlock = NULL;
  35.   } // End of Constructor for GIFFILETOOL
  36.  
  37. GIFFILETOOL::~GIFFILETOOL ()
  38.   {
  39.     DeInit ();
  40.   } // End of Destructor for GIFFILETOOL
  41.  
  42. BOOLEAN GIFFILETOOL::ReadHeader ()
  43.   {
  44.     BOOLEAN Ok;
  45.  
  46.     File.Seek ( fp, 0, FROM_BEGIN );
  47.     Ok = File.Read ( fp, &GIFHeader, sizeof(GIFHEADER) );
  48.     if (!Ok)
  49.       return FAILURE;
  50.  
  51.     if (strncmp(GIFHeader.ID,"GIF",3)!=0)
  52.       return FAILURE;
  53.     if ((strncmp(GIFHeader.Version,"87a",3)!=0)&&
  54.           (strncmp(GIFHeader.Version,"89a",3)!=0))
  55.       return FAILURE;
  56.  
  57.     return SUCCESS;
  58.   } // End of ReadHeader for GIFFILETOOL
  59.  
  60. BOOLEAN GIFFILETOOL::ReadScrDSC ()
  61.   {
  62.     BOOLEAN Ok;
  63.  
  64.     Ok = File.Read ( fp, &ScrDSC, 7 );
  65.     if (!Ok)
  66.       return FAILURE;
  67.  
  68.     #if defined (__MSBFIRST__)
  69.       SwapWord ( (WORD*)&ScrDSC.Width );
  70.       SwapWord ( (WORD*)&ScrDSC.Height );
  71.     #endif
  72.     return SUCCESS;
  73.   } // End of ReadScrDSC for GIFFILETOOL
  74.  
  75. BOOLEAN GIFFILETOOL::ReadGCT ( RGBPALETTE *Pal )
  76.   {
  77.     INT NumColors;
  78.     RGBCOLOR *Entry;
  79.  
  80.     NumColors = ScrDSC.NumColors ();
  81.     if (Pal==NULL)
  82.       {
  83.         RGBCOLOR Table[256];
  84.         File.Read ( fp, Table, sizeof(RGBCOLOR)*NumColors );
  85.         return SUCCESS;
  86.       } // End if
  87.  
  88.     Entry = Pal->GetEntry ();
  89.  
  90.     INT i;
  91.     for (i=0;i<NumColors;i++)
  92.       {
  93.         Entry[i].Red = (BYTE)File.GetCh ( fp );
  94.         Entry[i].Green = (BYTE)File.GetCh ( fp );
  95.         Entry[i].Blue = (BYTE)File.GetCh ( fp );
  96.       } // End for
  97.     return SUCCESS;
  98.   } // End of ReadGCT for GIFFILETOOL
  99.  
  100. BOOLEAN GIFFILETOOL::ReadImgDSC ()
  101.   {
  102.     BOOLEAN Ok;
  103.  
  104.     File.Seek ( fp, -1, FROM_CURRENT );
  105.     Ok = File.Read ( fp, &(ImgDSC.ID), sizeof(BYTE) );
  106.     if (!Ok)
  107.       return FAILURE;
  108.     Ok = File.Read ( fp, &(ImgDSC.xLeft), sizeof(SHORT) );
  109.     if (!Ok)
  110.       return FAILURE;
  111.     Ok = File.Read ( fp, &(ImgDSC.yLeft), sizeof(SHORT) );
  112.     if (!Ok)
  113.       return FAILURE;
  114.     Ok = File.Read ( fp, &(ImgDSC.Width), sizeof(SHORT) );
  115.     if (!Ok)
  116.       return FAILURE;
  117.     Ok = File.Read ( fp, &(ImgDSC.Height), sizeof(SHORT) );
  118.     if (!Ok)
  119.       return FAILURE;
  120.     Ok = File.Read ( fp, &(ImgDSC.Flags), sizeof(BYTE) );
  121.     if (!Ok)
  122.       return FAILURE;
  123.  
  124.     #if defined (__MSBFIRST__)
  125.       SwapWord ( (WORD*)&ImgDSC.xLeft );
  126.       SwapWord ( (WORD*)&ImgDSC.yLeft );
  127.       SwapWord ( (WORD*)&ImgDSC.Width );
  128.       SwapWord ( (WORD*)&ImgDSC.Height );
  129.     #endif
  130.  
  131.     return SUCCESS;
  132.   } // End of ReadImgDSC for GIFFILETOOL
  133.  
  134. BOOLEAN GIFFILETOOL::ReadLCT ( RGBPALETTE *Pal )
  135.   {
  136.     INT NumColors;
  137.     RGBCOLOR *Entry;
  138.  
  139.     NumColors = ImgDSC.NumColors ();
  140.  
  141.     if (Pal==NULL)
  142.       {
  143.         RGBCOLOR Table[256];
  144.         File.Read ( fp, Table, sizeof(RGBCOLOR)*NumColors );
  145.         return SUCCESS;
  146.       } // End if
  147.  
  148.     Entry = Pal->GetEntry ();
  149.     INT i;
  150.     for (i=0;i<NumColors;i++)
  151.       {
  152.         Entry[i].Red = (BYTE)File.GetCh ( fp );
  153.         Entry[i].Green = (BYTE)File.GetCh ( fp );
  154.         Entry[i].Blue = (BYTE)File.GetCh ( fp );
  155.       } // End for
  156.     return SUCCESS;
  157.   } // End of ReadLCT for GIFFILETOOL
  158.  
  159. BOOLEAN GIFFILETOOL::ReadImage ( IMAGE *Image, RGBPALETTE *Pal )
  160.   {
  161.     BOOLEAN Ok;
  162.  
  163.     Ok = ReadImgDSC ();
  164.     if (!Ok)
  165.       return FAILURE;
  166.  
  167.     if (ImgDSC.IsLCT())
  168.       {
  169.         Ok = ReadLCT ( Pal );
  170.         if (!Ok)
  171.           return FAILURE;
  172.       } // End if
  173.  
  174.     Ok = Image->Create ( IMAGE_8BIT, ImgDSC.Width, ImgDSC.Height );
  175.     if (!Ok)
  176.       return FAILURE;
  177.  
  178.     Ok = Decode ( Image );
  179.     if (!Ok)
  180.       return FAILURE;
  181.  
  182.     return SUCCESS;
  183.   } // End of ReadImage for GIFFILETOOL
  184.  
  185. BOOLEAN GIFFILETOOL::Decode ( IMAGE *Image )
  186.   {
  187.     INT i;
  188.     BOOLEAN Ok;
  189.  
  190.     GetCodeSize ();
  191.     InitDecoding ();
  192.  
  193.     StackPtr = 0;
  194.     NumBytes = 0;
  195.     ByteCount = 0;
  196.     CurByteMask = 256;
  197.  
  198.     CurCode = GetCode ();
  199.     while (CurCode==ClearCode)
  200.       CurCode = GetCode ();
  201.  
  202.     PreCode = CurCode;
  203.     FirstCh = PreCode;
  204.     PushCode ( PreCode );
  205.  
  206.     INT Row;
  207.     INT Pass = 0;
  208.  
  209.     if (ImgDSC.IsInterlaced())
  210.       Row = InterlacedData[Pass].Start;
  211.     else
  212.       Row = 0;
  213.  
  214.     for (i=0;i<Image->GetHeight();i++)
  215.       {
  216.         Ok = ReadRow ( Image, Row );
  217.         if (!Ok)
  218.           return FAILURE;
  219.  
  220.         if (ImgDSC.IsInterlaced())
  221.           {
  222.             Row += InterlacedData[Pass].Skip;
  223.             if (Row>=Image->GetHeight())
  224.               {
  225.                 Pass++;
  226.                 Row = InterlacedData[Pass].Start;
  227.               } // End if
  228.           } // End if
  229.         else
  230.           Row++;
  231.       } // End for
  232.  
  233.     return SUCCESS;
  234.   } // End of Decode for GIFFILETOOL
  235.  
  236. BOOLEAN GIFFILETOOL::ReadRow ( IMAGE *Image, INT Row )
  237.   {
  238.     DWORD Offset;
  239.     DWORD Wd;
  240.     BYTE *Buffer;
  241.  
  242.     Buffer = Image->SetOffset ( 0, Row );
  243.  
  244.     Wd = Image->GetWidth();
  245.     Offset = 0;
  246.  
  247.     // Place any unplaced code from previous to buffer
  248.     while ((Offset<Wd)&&(StackPtr>0))
  249.       {
  250.         Buffer[Offset] = (BYTE)PopCode ();
  251.         Offset++;
  252.       } // End while
  253.  
  254.     SHORT Index;
  255.  
  256.     while (Offset<Wd)
  257.       {
  258.         CurCode = GetCode ();
  259.         if (CurCode==ClearCode)
  260.           {
  261.             ClearTable ();
  262.             if (CurBits>=MAXBITS)
  263.               {
  264.                 CurBits = MinBits;
  265.                 MaxCode = (SHORT)((1<<CurBits));
  266.               } // End if
  267.             PreCode = GetCode ();
  268.             PushCode ( PreCode );
  269.           } // End if
  270.         else if (CurCode==EndCode)
  271.           {
  272.             break;
  273.           } // End else if
  274.         else
  275.           {
  276.             if (FindStr(CurCode))
  277.               {
  278.                 Index = CurCode;
  279.                 PushCode ( Suffix[Index] );
  280.                 Index = Prefix[Index];
  281.  
  282.                 while (Index!=NULLCODE)
  283.                   {
  284.                     PushCode ( Suffix[Index] );
  285.                     Index = Prefix[Index];
  286.                   } // End while
  287.                 FirstCh = GetFirstCh ();
  288.               } // End if
  289.             else
  290.               {
  291.                 PushCode ( FirstCh );
  292.                 Index = PreCode;
  293.                 PushCode ( Suffix[Index] );
  294.                 Index = Prefix[Index];
  295.  
  296.                 while (Index!=NULLCODE)
  297.                   {
  298.                     PushCode ( Suffix[Index] );
  299.                     Index = Prefix[Index];
  300.                   } // End while
  301.  
  302.                 FirstCh = GetFirstCh ();
  303.               } // End else
  304.  
  305.             AddNewString ( PreCode, FirstCh );
  306.             PreCode = CurCode;
  307.  
  308.             if (NextAvailCode>=MaxCode)
  309.               {
  310.                 if (CurBits<MAXBITS)
  311.                   {
  312.                     CurBits++;
  313.                     MaxCode = (SHORT)(1<<CurBits);
  314.                   } // End if
  315.               } // End if
  316.           } // End else
  317.  
  318.         while ((Offset<Wd)&&(StackPtr>0))
  319.           {
  320.             Buffer[Offset] = (BYTE)PopCode ();
  321.             Offset++;
  322.           } // End while
  323.       } // End while
  324.  
  325.     return SUCCESS;
  326.   } // End of ReadRow for GIFFILETOOL
  327.  
  328. void GIFFILETOOL::AddNewString ( SHORT Pre, SHORT New )
  329.   {
  330.     Prefix[NextAvailCode] = Pre;
  331.     Suffix[NextAvailCode] = New;
  332.     NextAvailCode++;
  333.   } // End of AddNewString for GIFFILETOOL
  334.  
  335. SHORT GIFFILETOOL::GetFirstCh ()
  336.   {
  337.     if (StackPtr>0)
  338.       return CodeStack[StackPtr-1];
  339.     return -1;
  340.   } // End of GetFirstCh for GIFFILETOOL
  341.  
  342. SHORT GIFFILETOOL::GetCode ()
  343.   {
  344.     INT Code;
  345.     INT BitMask;
  346.     INT i;
  347.  
  348.     BitMask = 1;
  349.     Code = 0;
  350.  
  351.     for (i=0;i<CurBits;i++)
  352.       {
  353.         if (CurByteMask>128)
  354.           CurByte = GetByte ();
  355.         if (CurByte&CurByteMask)
  356.           Code |= BitMask;
  357.  
  358.         BitMask <<= 1;
  359.         CurByteMask <<= 1;
  360.       } // End for
  361.     return (SHORT)Code;
  362.   } // End of GetCode for GIFFILETOOL
  363.  
  364. BYTE GIFFILETOOL::GetByte ()
  365.   {
  366.     ByteCount++;
  367.     if (ByteCount>=NumBytes)
  368.       {
  369.         BYTE Byte;
  370.         File.Read ( fp, &Byte, sizeof(BYTE) );
  371.         NumBytes = Byte;
  372.         if (NumBytes!=0)
  373.           File.Read ( fp, DataBlock, sizeof(BYTE)*NumBytes );
  374.         ByteCount = 0;
  375.       } // End if
  376.  
  377.     CurByteMask = 1;
  378.     return DataBlock[ByteCount];
  379.   } // End of GetByte for GIFFILETOOL
  380.  
  381. void GIFFILETOOL::PushCode ( SHORT Code )
  382.   {
  383.     if (StackPtr==HASHSIZE)
  384.       exit(-1);
  385.     CodeStack[StackPtr] = Code;
  386.     StackPtr++;
  387.   } // End of PushCode for GIFFILETOOL
  388.  
  389. SHORT GIFFILETOOL::PopCode ( )
  390.   {
  391.     StackPtr--;
  392.     return CodeStack[StackPtr];
  393.   } // End of PopCode for GIFFILETOOL
  394.  
  395. BOOLEAN GIFFILETOOL::InitDecoding ()
  396.   {
  397.     DeInit ();
  398.     CodeTable = new SHORT [HASHSIZE];
  399.     CodeStack = new SHORT [HASHSIZE];
  400.     Prefix = new SHORT [HASHSIZE];
  401.     Suffix = new SHORT [HASHSIZE];
  402.     DataBlock = new BYTE [256];
  403.  
  404.     if ((CodeTable==NULL)||
  405.          (CodeStack==NULL)||
  406.           (Prefix==NULL)||
  407.            (Suffix==NULL)||
  408.             (DataBlock==NULL))
  409.       return FAILURE;
  410.  
  411.     ClearTable ();
  412.  
  413.     return SUCCESS;
  414.   } // End of InitDecoding for GIFFILETOOL
  415.  
  416. void GIFFILETOOL::DeInit ()
  417.   {
  418.     if (CodeTable!=NULL)
  419.       delete CodeTable;
  420.  
  421.     if (CodeStack!=NULL)
  422.       delete CodeStack;
  423.  
  424.     if (Prefix!=NULL)
  425.       delete Prefix;
  426.  
  427.     if (Suffix!=NULL)
  428.       delete Suffix;
  429.  
  430.     if (DataBlock!=NULL)
  431.       delete DataBlock;
  432.  
  433.     CodeTable = NULL;
  434.     CodeStack = NULL;
  435.     Prefix = NULL;
  436.     Suffix = NULL;
  437.     DataBlock = NULL;
  438.   } // End of DeInitDecoding for GIFFILETOOL
  439.  
  440. BOOLEAN GIFFILETOOL::FindStr ( SHORT Code )
  441.   {
  442.     if ((Code>=0)&&(Code<NextAvailCode))
  443.       return TRUE;
  444.     return FALSE;
  445.   } // End of FindStr for GIFFILETOOL
  446.  
  447. void GIFFILETOOL::ClearTable ()
  448.   {
  449.     INT i;
  450.  
  451.     for (i=0;i<RootSize;i++)
  452.       {
  453.         Prefix[i] = NULLCODE;
  454.         Suffix[i] = (SHORT)i;
  455.       } // End for
  456.     NextAvailCode = (SHORT)(RootSize + 2);
  457.   } // End of ClearTable for GIFFILETOOL
  458.  
  459. INT GIFFILETOOL::GetCodeSize ()
  460.   {
  461.     BYTE Size;
  462.  
  463.     File.Read ( fp, &Size, sizeof(BYTE) );
  464.     MinBits = (SHORT)(Size+1);
  465.     CurBits = MinBits;
  466.     RootSize = (SHORT)(1<<Size);
  467.     ClearCode = RootSize;
  468.     EndCode = (SHORT)(RootSize+1);
  469.     NextAvailCode = (SHORT)(RootSize+2);
  470.     MaxCode = (SHORT)(1<<CurBits);
  471.     return Size;
  472.   } // End of GetCodeSize for GIFFILETOOL
  473.  
  474. BOOLEAN GIFFILETOOL::LoadImage ( IMAGE *Image, RGBPALETTE *Pal )
  475.   {
  476.     BOOLEAN Ok;
  477.  
  478.     if (Image==NULL)
  479.       return FAILURE;
  480.  
  481.     Ok = ReadHeader ();
  482.     if (!Ok)
  483.       return FAILURE;
  484.  
  485.     Ok = ReadScrDSC ();
  486.     if (!Ok)
  487.       return FAILURE;
  488.  
  489.     if (ScrDSC.IsGCT())
  490.       {
  491.         Ok = ReadGCT ( Pal );
  492.         if (!Ok)
  493.           return FAILURE;
  494.       } // End if
  495.  
  496.     SHORT Type;
  497.  
  498.     Type = 1;
  499.  
  500.     while (Type>0)
  501.       {
  502.         Type = (SHORT)File.GetCh ( fp );
  503.         switch (Type)
  504.           {
  505.             case 0x2C :  // Image Discriptor
  506.               Ok = ReadImage ( Image, Pal );
  507.               if (!Ok)
  508.                 break;
  509.               return SUCCESS;
  510.             default :
  511.               break;
  512.           } // End switch
  513.       } // End while
  514.  
  515.     DeInit ();
  516.     return Ok;
  517.   } // End of LoadImage for GIFFILETOOL
  518.  
  519. BOOLEAN GIFFILETOOL::WriteHeader ()
  520.   {
  521.     BOOLEAN Ok;
  522.  
  523.     strcpy (GIFHeader.ID,"GIF");
  524.     strcpy (GIFHeader.Version,"87a");
  525.  
  526.     File.Seek ( fp, 0, FROM_BEGIN );
  527.     Ok = File.Write ( fp, &GIFHeader, sizeof(GIFHEADER) );
  528.     if (!Ok)
  529.       return FAILURE;
  530.  
  531.     return SUCCESS;
  532.   } // End of WriteHeader for GIFFILETOOL
  533.  
  534. BOOLEAN GIFFILETOOL::WriteScrDSC ( INT Wd, INT Ht )
  535.   {
  536.     DWORD Size;
  537.  
  538.     ScrDSC.Width = (SHORT)Wd;
  539.     ScrDSC.Height = (SHORT)Ht;
  540.  
  541.     #if defined (__MSBFIRST__)
  542.       SwapWord ( (WORD*)&ScrDSC.Width );
  543.       SwapWord ( (WORD*)&ScrDSC.Height );
  544.     #endif
  545.  
  546.     ScrDSC.Flags = 0;
  547.     ScrDSC.Flags |= scdGCT;     // Set global color table
  548.     ScrDSC.Flags |= (8 - 1)<<4; // Set the Color Depth
  549.     ScrDSC.Flags &= ~scdSORT;   // Set non-sorted
  550.     ScrDSC.Flags |= 7;          // Set 256 colors
  551.  
  552.     ScrDSC.BGColor = 0;
  553.  
  554.     Size = File.Write ( fp, &ScrDSC, 7 );
  555.     if (Size!=7)
  556.       return FAILURE;
  557.     return SUCCESS;
  558.   } // End of WriteScrDSC for GIFFILETOOL
  559.  
  560. BOOLEAN GIFFILETOOL::WriteGCT ( RGBPALETTE *Pal )
  561.   {
  562.     RGBCOLOR *Entry;
  563.  
  564.     if (Pal==NULL)
  565.       return FAILURE;
  566.  
  567.     Entry = Pal->GetEntry ();
  568.  
  569.     INT i;
  570.     for (i=0;i<256;i++)
  571.       {
  572.         File.PutCh ( fp, Entry[i].Red );
  573.         File.PutCh ( fp, Entry[i].Green );
  574.         File.PutCh ( fp, Entry[i].Blue );
  575.       } // End for
  576.  
  577.     return SUCCESS;
  578.   } // End of WriteGCT for GIFFILETOOL
  579.  
  580. BOOLEAN GIFFILETOOL::InitEncoding ()
  581.   {
  582.     DeInit ();
  583.     CodeTable = new SHORT [HASHSIZE];
  584.     CodeStack = new SHORT [HASHSIZE];
  585.     Prefix = new SHORT [HASHSIZE];
  586.     Suffix = new SHORT [HASHSIZE];
  587.     DataBlock = new BYTE [256];
  588.  
  589.     if ((CodeTable==NULL)||
  590.          (CodeStack==NULL)||
  591.           (Prefix==NULL)||
  592.            (Suffix==NULL)||
  593.             (DataBlock==NULL))
  594.       return FAILURE;
  595.  
  596.     InitTable ();
  597.  
  598.     return SUCCESS;
  599.   } // End of InitEncoding for GIFFILETOOL
  600.  
  601. INT GIFFILETOOL::FindStr ( INT Pre, INT Cur )
  602.   {
  603.     INT Di,Index;
  604.     Index = (Cur<<HASH_BITS) ^ Pre;
  605.     if (Index==0)
  606.       Di = 1;
  607.     else
  608.       Di = CAPACITY - Index;
  609.  
  610.     BOOLEAN Done=FALSE;
  611.  
  612.          while (!Done)
  613.       {
  614.         if (CodeTable[Index]==-1) // This string is not found
  615.           {
  616.             Done = TRUE;
  617.             break;
  618.           } // End if
  619.  
  620.         if ((Prefix[Index]==Pre)&&(Suffix[Index]==Cur)) // Found
  621.           {
  622.             Done = TRUE;
  623.             break;
  624.                          } // End if
  625.  
  626.         Index -= Di;
  627.         if (Index<0)
  628.           {
  629.             while (Index<0)
  630.               Index += CAPACITY;
  631.             Di ++;
  632.           } // End if
  633.       } // End while
  634.  
  635.          if (Done)
  636.                 {}
  637.  
  638.          return Index;
  639.   } // End of FindStr for GIFFILETOOL
  640.  
  641. void GIFFILETOOL::InitTable ()
  642.   {
  643.     INT i;
  644.  
  645.     for (i=0;i<HASH_SIZE;i++)
  646.       {
  647.         CodeTable[i] = -1;
  648.         Suffix[i] = -1;
  649.         Prefix[i] = -1;
  650.       } // End for
  651.  
  652.     CurBits = MinBits;
  653.     NextAvailCode = (SHORT)(RootSize+2);
  654.     MaxCode = (SHORT)(1<<CurBits);
  655.   } // End of InitTable for GIFFILETOOL
  656.  
  657. void GIFFILETOOL::PutCodeSize ( BYTE CodeSize )
  658.   {
  659.     File.Write ( fp, &CodeSize, 1 );
  660.   } // End of PutCodeSize for GIFFILETOOL
  661.  
  662. void GIFFILETOOL::PutCode ( SHORT Code )
  663.   {
  664.     INT BitMask;
  665.     INT i;
  666.  
  667.     BitMask = 1;
  668.  
  669.     for (i=0;i<CurBits;i++)
  670.       {
  671.         if (Code&BitMask)
  672.           CurByte |= CurByteMask;
  673.         BitMask <<= 1;
  674.         CurByteMask <<= 1;
  675.         if (CurByteMask>128)
  676.           {
  677.             PutByte ();
  678.           } // End if
  679.       } // End for
  680.   } // End of PutCode for GIFFILETOOL
  681.  
  682. void GIFFILETOOL::PutByte ()
  683.   {
  684.     BYTE Count;
  685.     DataBlock[NumBytes++] = (BYTE)CurByte;
  686.     CurByte = 0;
  687.     CurByteMask = 1;
  688.  
  689.     if (NumBytes>=255)
  690.       {
  691.         Count = (BYTE)NumBytes;
  692.         File.Write ( fp, &Count, 1 );
  693.         File.Write ( fp, DataBlock, NumBytes );
  694.         NumBytes = 0;
  695.       } // End if
  696.   } // End of PutByte for GIFFILETOOL
  697.  
  698. void GIFFILETOOL::AddNewString ( INT Pre, INT Cur, INT Index )
  699.   {
  700.     CodeTable[Index] = NextAvailCode;
  701.     NextAvailCode++;
  702.     Prefix[Index] = (SHORT)Pre;
  703.     Suffix[Index] = (SHORT)Cur;
  704.   } // End of AddNewString for GIFFILETOOL
  705.  
  706. void GIFFILETOOL::FlushAll ()
  707.   {
  708.     BYTE Count;
  709.     Count = (BYTE)NumBytes;
  710.     File.Write ( fp, &Count, 1 );
  711.     File.Write ( fp, DataBlock, NumBytes );
  712.   } // End of FlushAll for GIFFILETOOL
  713.  
  714. BOOLEAN GIFFILETOOL::WriteRow ( IMAGE *Image, INT Row, INT Sx, INT Wd )
  715.   {
  716.     BYTE *Buffer;
  717.  
  718.     Buffer = Image->SetOffset ( Sx, Row );
  719.     if (Buffer==NULL)
  720.       return FAILURE;
  721.  
  722.     INT Offset;
  723.     INT Index;
  724.     Offset = 0;
  725.  
  726.     if (Row==0)
  727.       PreCode = Buffer[Offset++];
  728.  
  729.     while (Offset<Wd)
  730.       {
  731.         CurCode = Buffer[Offset];
  732.         Offset++;
  733.         Index = FindStr(PreCode,CurCode);
  734.         if (CodeTable[Index]!=-1)
  735.           {
  736.             PreCode = CodeTable[Index];
  737.           } // End if
  738.         else
  739.           {
  740.             AddNewString ( PreCode, CurCode, Index );
  741.             PutCode ( PreCode );
  742.             PreCode = CurCode;
  743.             if (CodeTable[Index]>MaxCode-1)
  744.               {
  745.                 if (CurBits>=MAXBITS)
  746.                   {
  747.                     PutCode ( ClearCode ); // Clear Code
  748.                     InitTable ();
  749.                   } // End if
  750.                 else
  751.                   {
  752.                     CurBits++;
  753.                     MaxCode = (SHORT)(1<<CurBits);
  754.                   } // End else
  755.               } // End if
  756.           } // End else
  757.       } // End while
  758.     return SUCCESS;
  759.   } // End of WriteRow for GIFFILETOOL
  760.  
  761. BOOLEAN GIFFILETOOL::Encode ( IMAGE *Image, INT Sx, INT Sy, INT Wd, INT Ht )
  762.   {
  763.     MinBits = 8+1;
  764.     RootSize = (1<<8);
  765.     ClearCode = RootSize;
  766.     EndCode = (SHORT)(RootSize+1);
  767.     CurBits = MinBits;
  768.     NextAvailCode = (SHORT)(RootSize+2);
  769.     MaxCode = (SHORT)((1<<CurBits));
  770.  
  771.     PutCodeSize ( 8 );
  772.     InitEncoding ();
  773.  
  774.     NumBytes = 0;
  775.     CurByteMask = 1;
  776.     CurByte = 0;
  777.  
  778.     PutCode ( ClearCode ); // Clear Code
  779.  
  780.     INT i;
  781.     BOOLEAN Ok;
  782.  
  783.     for (i=Sy;i<Sy+Ht;i++)
  784.       {
  785.         Ok = WriteRow ( Image, i, Sx, Wd );
  786.         if (!Ok)
  787.           return FAILURE;
  788.       } // End for
  789.  
  790.     PutCode ( PreCode );
  791.     PutCode ( EndCode ); // Put End Code
  792.     FlushAll ();
  793.  
  794.     return SUCCESS;
  795.   } // End of Encode for GIFFILETOOL
  796.  
  797. BOOLEAN GIFFILETOOL::WriteImgDSC ( INT Wd, INT Ht )
  798.   {
  799.     BOOLEAN Ok;
  800.  
  801.     ImgDSC.ID = 0x2C;
  802.     ImgDSC.xLeft = 0;
  803.     ImgDSC.yLeft = 0;
  804.     ImgDSC.Width = (SHORT)Wd;
  805.     ImgDSC.Height = (SHORT)Ht;
  806.     ImgDSC.Flags = 0;
  807.     ImgDSC.Flags |= 7;
  808.  
  809.     #if defined (__MSBFIRST__)
  810.       SwapWord ( (WORD*)&ImgDSC.xLeft );
  811.       SwapWord ( (WORD*)&ImgDSC.yLeft );
  812.       SwapWord ( (WORD*)&ImgDSC.Width );
  813.       SwapWord ( (WORD*)&ImgDSC.Height );
  814.     #endif
  815.  
  816.     Ok = File.Write ( fp, &(ImgDSC.ID), sizeof(BYTE) );
  817.     if (!Ok)
  818.       return FAILURE;
  819.     Ok = File.Write ( fp, &(ImgDSC.xLeft), sizeof(SHORT) );
  820.     if (!Ok)
  821.       return FAILURE;
  822.     Ok = File.Write ( fp, &(ImgDSC.yLeft), sizeof(SHORT) );
  823.     if (!Ok)
  824.       return FAILURE;
  825.     Ok = File.Write ( fp, &(ImgDSC.Width), sizeof(SHORT) );
  826.     if (!Ok)
  827.       return FAILURE;
  828.     Ok = File.Write ( fp, &(ImgDSC.Height), sizeof(SHORT) );
  829.     if (!Ok)
  830.       return FAILURE;
  831.     Ok = File.Write ( fp, &(ImgDSC.Flags), sizeof(BYTE) );
  832.     if (!Ok)
  833.       return FAILURE;
  834.     return SUCCESS;
  835.   } // End of WriteImgDSC for GIFFILETOOL
  836.  
  837. BOOLEAN GIFFILETOOL::WriteImage ( IMAGE *Image, INT Sx, INT Sy, INT Wd, INT Ht )
  838.   {
  839.     BOOLEAN Ok;
  840.  
  841.     Ok = WriteImgDSC ( Wd, Ht );
  842.     if (!Ok)
  843.      return FAILURE;
  844.  
  845.     Ok = Encode ( Image, Sx, Sy, Wd, Ht );
  846.     if (!Ok)
  847.      return FAILURE;
  848.  
  849.     BYTE End = 0;
  850.  
  851.     File.Write ( fp, &End, 1 );
  852.  
  853.     return SUCCESS;
  854.   } // End of WriteImage for GIFFILETOOL
  855.  
  856. BOOLEAN GIFFILETOOL::SaveImage ( IMAGE *Image, LONG Sx, LONG Sy,
  857.                                  LONG Wd, LONG Ht, RGBPALETTE *Pal )
  858.   {
  859.     if (Image==NULL)
  860.       return FAILURE;
  861.  
  862.     BOOLEAN Ok;
  863.  
  864.     Ok = WriteHeader ();
  865.     if (!Ok)
  866.       return FAILURE;
  867.  
  868.     Ok = WriteScrDSC ( Wd, Ht );
  869.     if (!Ok)
  870.       return FAILURE;
  871.  
  872.     Ok = WriteGCT ( Pal );
  873.     if (!Ok)
  874.       return FAILURE;
  875.  
  876.     Ok = WriteImage ( Image, Sx, Sy, Wd, Ht );
  877.     if (!Ok)
  878.       return FAILURE;
  879.  
  880.     BYTE EndTrailer = 0x3B;
  881.  
  882.     File.Write ( fp, &EndTrailer, 1 );
  883.  
  884.     return SUCCESS;
  885.   } // End of SaveImage for GIFFILETOOL
  886.